<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 封装一个Vue实现数据代理
        function Vue({ data }) {
            // 在Vue内部把数据放在了vm._data上
            this._data = data
            // 数据代理:遍历_data的数据 在vm上放一份
            for (let key in this._data) {
                Object.defineProperty(this, key, {
                    get: function proxyGetter() {
                        return this._data[key]
                    },
                    set: function proxySetter(val) {
                        this._data[key] = val
                    }
                })
            }
            observer(this._data);
        }
        //封装一个函数,专门用来做数据劫持的(可以认为是发布订阅模型中的发布者)
        function observer(data) {
            if (typeof data !== "object" || data === null) return;
            for (let key in data) {
                //数据劫持功能
                defineReactive(data, key);
            }
        }

        function defineReactive(data, key) {
            let value = data[key]
            observer(value)
            Object.defineProperty(data, key, {
                get() {
                    return value
                },
                set(newVal) {
                    value = newVal
                    console.log("通知视图更新")
                    test()
                }
            })
        }
        const vm = new Vue({
            data: {
                count: 1,
                price: 299,
                score: {
                    math: 80,
                    en: 30,
                },
            },
        });

        console.log(vm);

        function test() {
            console.log(`我是模板,当前的价格是${vm.price},数量是${vm.count}`);
        }

        //初始化的时候要获取一次数据
        test();
    </script>
</body>

</html>